################################################################################
# This is simple GAE file manager

# Lets start with define modeles
# We're need to fetch from server collection list (Folsers)
#   and file list (FileList)

class Folder extends Backbone.Model #

  url:'../uploads/collection'       # On server Folder called Collection

  defaults:
    id:null
    title:null
    date:null

################################################################################

class File extends Backbone.Model
  # We redefine the 'sync' method where we want to swich the CRUD off.
  sync:()-> 0

  defaults:
    id:null
    title:null
    cover: false
    thumb:null
    checked:false # We will use this property for group operations

################################################################################

class FolderList extends Backbone.Collection

  url:'../uploads/collections'  # Folders list

  model:Folder

  parse:(response) -> response.data # server returns {data:[list]}

#######
class FileList extends Backbone.Collection

  url:'../uploads'

  model:File

  parse:(response) -> response.data



################################################################################
# Now, lets work with views
# each one conforms to other model
# !! Models have CRUD !!

class FolderView extends Backbone.View #this work with Folder model
  tagName:'tr'

  template: _.template $("#collection-item-template").html()

  events:
    "click #delete":'delete'
    "click #folder-edit-btn": 'edit'

  edit:->
    model = @model

    name = @$el.find('#folder-name')
    input = @$el.find('#folder-edit')

    name.hide()
    input.show()

    input.on 'blur', ()-> name.show(); input.hide() # hide input on blur

    input.Enter ()-> model.save {title:input.val()} #save model POST on server


    model.on 'sync', ()=>                           #on success
      @render()
      console.log('Succefully updated')

    model.on 'error', () ->  view.render()          #on fail


  delete:->
    yeap = confirm 'A you sure you want to delete collection of files?'
    id = @model.id
    url = @model.url
    if yeap

      @model.destroy {
        url: url+'/'+id,
        success:-> $('#'+id).remove() #delete from DOM
      }


  render:->
    # _.temlate gets json
    @$el.html @template( @model.toJSON() )
    @$el.find('#folder-edit').hide()
    return @


################################################################################

# File view (thumb)
class FileView extends Backbone.View
  tagName:'li'

  template: _.template $('#file-item').html()

  render:->
    @$el.html(@template(@model.toJSON()))
    return @

  events:
   "click": "toogle"


  toogle:->
    #Simle toogler
    @.model.save {checked: not @model.get 'checked' } #CRUD swiched off manually,

    if @.model.get 'checked'                           #     see model.
       $('#'+@.model.id).parent().addClass 'checked'
    else
       $('#'+@.model.id).parent().removeClass 'checked'



################################################################################


# Uploads List view
class FileUpload extends Backbone.View
  el:$('#upload-form'),
  @collection:''
  initialize:->

    @data = new FormData()
    $("#upload-spin").hide()

    $("#browse").on 'change', => @compute()

    clearFileInput $("#browse")[0]  # ffox saves form even if reload
    $("#start-upload").hide() # hide from useless clickers


  events:
    "click #start-upload": 'send'

  compute:->
    form = $("#browse")[0]

    _.each form.files, (e,i)=>
        @data.append('file', e) # add files to FormData

    collection = @collection
    @data.append('collection', decodeURIComponent(collection))

    @len = form.files.length # num of files

    if @len
      $("#start-upload").show()

  send:->

    if @len # check file checkd
      $("#start-upload").show()

      $.get '../uploads/session', (url)=> #get upload session

        $("#upload-spin").show() # simple stupid spinner insted of civil progress =)


        $.ajax {
          url: url,
          data: @data,
          cache: false,
          contentType: false,
          processData: false,
          type: 'POST',
          success: (data)=>
            $("#upload-spin").hide()
            $("#start-upload").hide()
            clearFileInput($("#browse")[0])
            @data = new FormData()
            @len = null
          }

################################################################################

class CreateFolder extends Backbone.View

  initialize:->
    @folder = new Folder()
    $('#folder-create').hide()

    input = $("#folder-create input").first()

    ##
    input.Enter => ##
       @folder.save { title:input.val() }

    ##
    $('#folder-create #ok').on 'mousedown', => #on ok button
       @folder.save { title:input.val() } # impliment new record

    ##
    $('#folder-create input').on 'blur', -> #hide input with delay
       setTimeout (->
        $('#folder-create').hide()
        $('#folder-new').show()
        ), 2500

    ##
    $('#folder-new').on 'mousedown', ->
       $('#folder-new').hide()
       $('#folder-create').show()

    ##
    @folder.on 'sync', ->
       $('#folder-new').show()
       $('#folder-create').hide()
       $('#folder-grid tr').remove()


    @folder.on 'error' , ->
       input.addClass('error')
       console.log('error')


################################################################################

# Main view
class Manager extends Backbone.View

  el:$('#file-manager')

  events:
   "click #fresh-file-list": "files_fetch"
   "click #files-download": "files_download"
   "click #files-delete": "files_delete"

  @collection:''

  initialize:->

    @limit=12 #mega simple stupid pagination
    @offset=0 #for files collection

    @offsetF=0
    @limitF=12#for folders collection

    @files = new FileList()

    #@files_fetch() # fetch methods calls from route
    @files_paginate() # 'sync' event init in paginate method, remind it

    @folders = new FolderList()

    #@folders_fetch() #
    @folders_paginate()

    creator = new CreateFolder

    creator.folder.on 'sync', =>
      setTimeout (=> @folders_fetch()), 50 #in case of mega slow data recording



  files_delete:->

    checked = @files.where({checked:true})

    _.each checked, (i)->
      i.sync = Backbone.sync # if was off in model to prevent
      i.destroy()            #            update because of checked attribute

    @files_fetch()


  files_download: ->
    checked = @files.where({checked:true})

    _.each checked, (i)->
      id = i.id
      $.get '../uploads/download-session/'+id, (url) ->
          downloadURL(url)





  #load files
  files_fetch:->
    $('#file-grid li').remove()
    @files.fetch({data:{limit:@limit,offset:@offset, collection:@collection}})


  files_paginate:->

    #Pagination
    prev = $('#files-prev') # previous button
    next = $("#files-next") # forward button
    firstRecord=0 # to hide prev button

    prev.hide() # at once

    prev.click =>
      $('#file-grid li').remove() # clean view
      assert @offset > 0   #trow even if prev wasnt hide on first page

      @offset = @offset - @limit
      @files_fetch()

    next.click =>
      @offset = @offset + @limit
      @files_fetch()

    @files.on 'sync', =>

      if @files.length
        next.show() # if files is really exist

      if @offset
        prev.show() # if it already got forward

      if @files.length < @limit
        next.hide() # if it's last page or page isn't full

      if not firstRecord or not @offset
        firstRecord = @files.models[0].id # look at loop below


      @files.each (item) -> # each method comes from underscore and depend on it

        if item.id==firstRecord
          prev.hide()  # if first record occurs on page

        # Remove dublicate by item.id if exist
        $('#file-grid')
        .find("#"+item.id)
        .parent()
        .remove()

        view = new FileView({model:item}) #create new view|
        # Append current tempate to file grid
        $('#file-grid').append(view.render().el)



  #load folders
  folders_fetch:->
    $('#folder-grid tr').remove()
    @folders.fetch({data:{limit:@limitF,offset:@offsetF}})


  folders_paginate: ->

    #Pagination
    prev = $('#collections-prev')
    next = $("#collections-next")
    firstRecord=0;

    prev.hide()

    prev.click =>
      assert @offsetF > 0
      @offsetF = @offsetF - @limitF
      @folders_fetch()

    next.click =>
      @offsetF = @offsetF + @limitF
      @folders_fetch()


    # Folders render
    @folders.on 'sync', =>

      if @folders.length
        next.show()

      if @offsetF
        prev.show()

      if @folders.length < @limitF
        next.hide()

      if not firstRecord or not @offsetF
        firstRecord = @folders.models[0].id



      @folders.each (item, index)->

        if item.id==firstRecord
          prev.hide()

        $('#folder-grid')
        .find("#"+item.id)
        .parent()
        .remove()

        view = new FolderView({model:item})


        $('#folder-grid').append(view.render().el)

      $("#folder-name").click =>
          @offset=0 # reset once choose new folder


################################################################################


# And finally spice up with some routes
class Route extends Backbone.Router

  initialize:->
    @route(/^file-list\/(.*)?/, 'files')
    @route(/^upload-file\/(.*)?/, 'upload')

    @manager = new Manager
    @uploader = new FileUpload




  routes:
    "collection-list/":  "folders"

  toogle:(target)->
    $('#file-manager .content').removeClass('active')
    $('ul.tabs li').removeClass('active')
    $('#'+target).addClass('active')

    $("a[href='#"+target+"/']")
    .parent()
    .addClass("active")





  files:(query)->
    @toogle('file-list')
    @manager.collection = query
    @manager.files_fetch()
    $('#current-place').html(decodeURIComponent(query or '../'))

  folders: ->
    @toogle('collection-list')
    @manager.folders_fetch()

  upload:(query)->
    @toogle('upload-file')
    @uploader.collection = query
    $('#upload-place').html(decodeURIComponent(query or '../' ))

main = new Route

Backbone.history.start()
main.navigate("/file-list/", true)
# tA-Da PurUm-puM-pUm bZzzzz

